#include "esp_adc_cal.h"
#include "driver/adc.h"

// 定义引脚
#define xdc_U_PIN ADC1_CHANNEL_5 // 蓄电池电压的模拟输入引脚
#define xdc_I_PIN ADC1_CHANNEL_3 // 蓄电池电压的模拟输入引脚

#define tyn_U_PIN ADC1_CHANNEL_6 // 太阳能电压的模拟输入引脚
#define tyn_I_PIN ADC1_CHANNEL_4 // 太阳能电流的模拟输入引脚

#define MOS_PIN ADC1_CHANNEL_7 // MOS温度模拟输入引脚

#define ADC_ATTEN_11 ADC_ATTEN_11db // 11dB衰减器// 默认3.3V的参考电压

#define NO_OF_SAMPLES 12 // ADC采样次数
int adc = 0;

// 用于存储校准数据
esp_adc_cal_characteristics_t adc_chars;

// 初始化ADC和校准
void initADC()
{
    // 选择ADC单元和通道
    adc1_config_width(ADC_WIDTH_BIT_12);

    adc1_config_channel_atten(tyn_U_PIN, ADC_ATTEN_11); // 配置ADC通道为12dB衰减器
    adc1_config_channel_atten(xdc_U_PIN, ADC_ATTEN_11); // 配置ADC通道为12dB衰减器
    adc1_config_channel_atten(tyn_I_PIN, ADC_ATTEN_11); // 配置ADC通道为12dB衰减器
    adc1_config_channel_atten(xdc_I_PIN, ADC_ATTEN_11); // 配置ADC通道为12dB衰减器
    adc1_config_channel_atten(MOS_PIN, ADC_ATTEN_11);   // 配置ADC通道为12dB衰减器

    esp_adc_cal_characterize(ADC_UNIT_1, ADC_ATTEN_11, ADC_WIDTH_BIT_12, 0, &adc_chars);
}

void tyn_u()
{
    static int adc_reading = 0;
    adc_reading += esp_adc_cal_raw_to_voltage(adc1_get_raw(tyn_U_PIN), &adc_chars);
    if (adc == NO_OF_SAMPLES)
    {
        adc_reading /= NO_OF_SAMPLES;
        if (adc_reading == 0)
        {
            tyn_U = 0;
        }
        else
        {
            tyn_U = ((R1 + R2) / R2 * (adc_reading + 23));
        }
        adc_reading = 0;
    }
}

void tyn_i()
{
    static float adc_reading = 0;
    adc_reading += esp_adc_cal_raw_to_voltage(adc1_get_raw(tyn_I_PIN), &adc_chars);
    if (adc == NO_OF_SAMPLES)
    {
        adc_reading /= NO_OF_SAMPLES;
        if (adc_reading == 0)
        {
            tyn_I = 0;
        }
        else
        {
            tyn_I = (adc_reading + 35.7) / 52.37 * 1000;
        }
        adc_reading = 0;
    }
}

void xdc_u()
{
    static float adc_reading = 0;
    adc_reading += esp_adc_cal_raw_to_voltage(adc1_get_raw(xdc_U_PIN), &adc_chars);
    if (adc == NO_OF_SAMPLES)
    {
        adc_reading /= NO_OF_SAMPLES;
        if (adc_reading == 0)
        {
            adc_reading = 0;
        }
        else
        {
            xdc_U = ((R3 + R4) / R4 * (adc_reading + 23));
        }
        adc_reading = 0;
    }
}

void xdc_i()
{
    if (xdc_U > 0)
    {
        xdc_I = tyn_U * tyn_I * 0.95 / xdc_U;
    }
    // static float adc_reading = 0;
    // adc_reading += esp_adc_cal_raw_to_voltage(adc1_get_raw(xdc_I_PIN), &adc_chars);
    // if (adc == NO_OF_SAMPLES)
    // {
    //     adc_reading /= NO_OF_SAMPLES;
    //     xdc_I = map(adc_reading, 0, 3139, 0, 64061);
    //     adc_reading = 0;
    // }
}

void MOS_t()
{
    static float adc_reading = 0;
    adc_reading += esp_adc_cal_raw_to_voltage(adc1_get_raw(MOS_PIN), &adc_chars) + 20;
    if (adc == NO_OF_SAMPLES)
    {
        adc_reading /= NO_OF_SAMPLES;
        if (adc_reading == 0)
        {
            MOS_T = 0;
        }
        else
        {
            MOS_T = map(adc_reading, 715 * 2, 2350 * 2, 1200, 6100) / 100.00;
        }
        adc_reading = 0;
    }
}
void tyn_p()
{
    tyn_P = tyn_U * tyn_I / 1000000;
}

unsigned long preHeartTick2 = 0; // 心跳
unsigned long preHeartTick3 = 0; // 心跳
void tyn_w()
{
    if (tyn_I > 0 && millis() - preHeartTick2 >= 1000)
    {
        static float k = kWh;
        Q += (xdc_I / 3600000);
        kWh += (tyn_P / 3600000);
        if (kWh - k > 0.02 && millis() - preHeartTick3 >= 60000)
        {
            sendtoTCPServer("cmd=2&uid=" + UID +
                            "&topic=" + TOPIC +
                            "/up&msg=保存\r\n");
            k = kWh;
            operateOnDataInFile("/data.txt", "Q", "W", Q);
            operateOnDataInFile("/data.txt", "kWh", "W", kWh);
            preHeartTick3 = millis();
        }
        preHeartTick2 = millis();
    }
}

void qidongADC()
{
    adc++;
    tyn_u();
    tyn_i();
    tyn_p();
    tyn_w();
    xdc_u();
    xdc_i();
    MOS_t();
    if (adc == NO_OF_SAMPLES)
    {
        adc = 0;
        // if (!digitalRead(0))
        // {
        //     for (size_t i = 0; i < 20; i++)
        //     {
        //         digitalWrite(spk_PIN, !digitalRead(spk_PIN)); // 指示灯引脚
        //         delay(100);
        //     }
        //     digitalWrite(spk_PIN, LOW); // 指示灯引脚
        //     ESP.restart();
        //     while (1)
        //     {
        //         delay(100);
        //     }
        // }
    }
}
